package com.example.win.android_banduyujia.ui.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import java.util.ArrayList;

/**
 * Created by Win on 2015/8/27.
 */
public class TimeSelectView extends View implements View.OnTouchListener, SelectListener{

    private boolean isMeasure = false;
    private Bitmap  bmp;
    private Path path; // 裁剪路径
    private Paint  textPaint,bgPaint;
    private Paint  bmpPaint, linePaint;
    private Paint  roundPaint;

    private float  viewW,viewH,cycleR;
    private float  startX, startY;
    private float  defaultTextSize = 80;

    private ArrayList<SelectItem>  items = new ArrayList<SelectItem>();

    private int maxItem = 5;
    private double  down;
    private SelListener  sl;

    public TimeSelectView(Context context) {
        super(context);
        InitPaint();
    }

    public TimeSelectView(Context context, AttributeSet attrs) {
        super(context, attrs);
        InitPaint();
    }

    public TimeSelectView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        InitPaint();
    }

    /*@TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public TimeSelectView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr,defStyleRes);
        InitPaint();
    }*/

    private void InitPaint() {
       bmpPaint = new Paint();
       bmpPaint.setAntiAlias(true);
       bmpPaint.setStyle(Paint.Style.FILL);

       textPaint = new Paint();
       textPaint.setColor(Color.rgb(120, 103, 173));
       textPaint.setTypeface(Typeface.DEFAULT);

       bgPaint = new Paint();
       bgPaint.setAntiAlias(true);
       bgPaint.setStyle(Paint.Style.FILL);
       bgPaint.setColor(Color.rgb(227, 222, 242));

       linePaint = new Paint();
       linePaint.setAntiAlias(true);
       linePaint.setStyle(Paint.Style.FILL);
       linePaint.setColor(Color.rgb(120, 103, 173));

       roundPaint = new Paint();
       roundPaint.setColor(Color.rgb(120,103,173));
       roundPaint.setStrokeWidth(2);
    }

    @Override
    protected void onLayout(boolean changed, int mleft, int top, int right, int bottom) {
        super.onLayout(changed, mleft, top, right, bottom);
        if(!isMeasure){
            setOnTouchListener(this);

            viewW = getWidth();
            viewH = getHeight();
            cycleR = viewW > viewH ? viewH / 2 : viewW / 2;

            path = new Path();
            path.addCircle(cycleR, cycleR, cycleR, Path.Direction.CCW);

            itemHeight = cycleR * 2 / maxItem;
            defaultTextSize =((cycleR / maxItem) + 10);
            left = cycleR * 3 / 4 ;

            isMeasure = true;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.clipPath(path);
        canvas.drawCircle(cycleR, cycleR, cycleR, bgPaint);

        int size = items.size();
        float sX = cycleR * 3 / 4;
        float sY = cycleR - itemHeight / 2;
        float stopX = (float)(Math.sqrt(cycleR * cycleR -(sY - cycleR) * (sY - cycleR)) + cycleR) - 2;
        for(int i =0; i < size; i++){
            if(items.get(i).isVisible(cycleR * 2)){
                SelectItem  item = items.get(i);
                if(item.rect.top + itemHeight / 2 - cycleR <= 0){
                    textPaint.setTextSize((float)(defaultTextSize + item.rect.top * 0.12));
                }else{
                    textPaint.setTextSize((float)(defaultTextSize + (cycleR * 2 - item.rect.bottom) * 0.12));
                }
                textPaint.setAlpha((int)(textPaint.getTextSize()*0.8));
                canvas.drawText(item.text, item.rect.left, item.rect.top + itemHeight*2/5 + textPaint.getTextSize()/2, textPaint);
            }
        }
       canvas.drawLine(sX, sY, stopX, sY, linePaint);
       canvas.drawLine(sX, sY + itemHeight, stopX, sY + itemHeight, linePaint);

       Path path = new Path();
       path.moveTo(cycleR / 4, cycleR - (itemHeight / 3));
       path.lineTo(cycleR / 4, cycleR + (itemHeight / 3));
       path.lineTo((float)(cycleR * 0.7),cycleR);
       path.close();
       canvas.drawPath(path, linePaint);
       //drawOutCycle(canvas, cycleR, cycleR-2);
    }

    private void drawOutCycle(Canvas canvas, float centre, float radius) {
            canvas.drawCircle(centre, centre, radius, roundPaint); // 画出圆环
    }

    private void sortItem(float move) {
        int  size = items.size();
        float right, top;

        for(int i =0; i<size; i++){
            top = items.get(i).rect.top + move;
            right = getWidth();
            items.get(i).setRect(new RectF(left, top, right, top + itemHeight));
        }
    }

    float itemHeight;
    float moveLength, margin;
    int   mI;
    private float left;

    private void sort(float move) {
        int size = items.size();
        float right, top;
        for(int i=0; i < size; i++){
            top = items.get(i).rect.top + move;
            right = getWidth();
            items.get(i).setRect(new RectF(left, top, right, top + itemHeight));
        }
    }

    public void init(final ArrayList<String>  lst) {
        if(lst == null || lst.size() == 0){
            Toast.makeText(getContext(), "数据不能为空", Toast.LENGTH_LONG).show();
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
               while (!isMeasure){
                   try {
                        Thread.sleep(50);
                   }catch (InterruptedException e){

                   }
               }
                setItems(lst);
            }
        }).start();
    }

    public void setItems(ArrayList<String> lst) {
        int length = lst.size();
        for(int i =0; i < length; i++){
            SelectItem  item =  new SelectItem(new RectF(), lst.get(i));
            items.add(item);
        }
        int size = items.size();
        if(size < maxItem && size > 0){
            for(int i = size / 2; i >= 0; i--){
                float top = cycleR - (size / 2 - i) *itemHeight - (itemHeight / 2);
                float right=(float)(Math.sqrt(cycleR*cycleR - (top - cycleR)*(top - cycleR)) + cycleR);
                items.get(i).setRect(new RectF(left, top, right, top + itemHeight));
            }
            for (int i = size / 2 + 1; i < size; i++){
                float top = items.get(i - 1).getRect().top + itemHeight;
                float right = (float)(Math.sqrt(cycleR * cycleR - (top + itemHeight - cycleR)*(top + itemHeight-cycleR)) + cycleR);
                items.get(i).setRect(new RectF(left, top, right, top + itemHeight));
            }
        }else{
            float  top;
            float  right;
            for(int i=0; i<size;i++){
                top = i * itemHeight;

                right = getWidth();
                items.get(i).setRect(new RectF(left, top, right, top + itemHeight));
            }
            myHandler.sendEmptyMessage(1);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        if(bmp != null){
            bmp.recycle();
            bmp = null;
        }
        if(t != null && t.isAlive()){
            isRun = false;
            t = null;
        }
        super.onDetachedFromWindow();
    }

    Thread  t;
    boolean isRun = false;
    boolean isMovew;
    float   downY;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(isRun){
            return true;
        }
        if(!isInTouchArea(event) && event.getAction() != MotionEvent.ACTION_UP){
            onUp(event);
            return true;
        }
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                 startY = event.getY();
                 downY = startY;
                 down = System.currentTimeMillis();
                 isMovew = false;
                break;
            case MotionEvent.ACTION_MOVE:
                 if(Math.abs((event.getY() - startY)) >= itemHeight / 50){
                     isMovew = true;
                     sortItem(event.getY() - startY);
                     invalidate();
                     startY = event.getY();
                 }
                break;
            case MotionEvent.ACTION_UP:
                  if((System.currentTimeMillis() - down) < 200 && !isMovew){
                      if(sl != null && getItem(event) != null){
                          sl.onClick(getItem(event).text);
                      }
                      if(isInTouchArea(event)){
                          select(event);
                      }
                      return true;
                  }
                onUp(event);
                break;
        }
        return true;
    }

    private void onUp(MotionEvent event) {
        if(items.get(0).rect.top + itemHeight / 2 > cycleR){
            t = new Thread(new Runnable() {
                @Override
                public void run() {
                   isRun = true;
                   for(int i = (int) items.get(0).rect.top; i > cycleR - itemHeight / 2; i -=itemHeight / 10){
                        try{
                            if(isRun){
                                sortItem(-itemHeight / 10);
                                Thread.sleep(10);
                                myHandler.sendEmptyMessage(1);
                            }else{
                                break;
                            }
                        }catch (InterruptedException e){

                        }
                   }
                 isRun = false;
                }
            });
            t.start();
        }else if(items.get(items.size() -1).rect.top + itemHeight / 2 < cycleR){
            t = new Thread(new Runnable() {
                @Override
                public void run() {
                    isRun = true;
                    for(int i=(int)items.get(items.size() - 1).rect.top; i< cycleR - itemHeight / 2; i += itemHeight / 10){
                        try{
                            if(isRun){
                                sortItem(itemHeight / 10);
                                Thread.sleep(10);
                                myHandler.sendEmptyMessage(1);
                            }
                        }catch (InterruptedException e){

                        }
                    }
                    isRun = false;
                }
            });
            t.start();
        }
        startY = event.getY();
        if(!isRun){
            setMid();
        }
    }

    Handler  myHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            invalidate();
        }
    };

    private void select(MotionEvent event) {
        int size = items.size();
        for (int i = 0; i < size; i++) {
            if (items.get(i).isVisible(cycleR * 2)) {
                if (items.get(i).isInRect(event.getX(), event.getY())) {
                    margin = items.get(i).rect.top - (cycleR - itemHeight / 2);
                    if (Math.abs(margin) >= itemHeight / 2) {
                        t = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                isRun = true;
                                Rect rect = new Rect();
                                textPaint.getTextBounds(items.get(items.size() - 1).text, 0, 2, rect);
                                for (float i = Math.abs(margin); i > 0; i -= Math.abs(margin) / 10) {
                                    try {
                                        if (isRun) {
                                            sort(-margin / 10);
                                            Thread.sleep(10);
                                            myHandler.sendEmptyMessage(1);
                                        } else {
                                            break;
                                        }
                                    } catch (InterruptedException e) {

                                    }
                                }
                                setMid();
                                isRun = false;
                            }
                        });
                        t.start();
                    }
                    break;
                }
            }
        }
    }

    private void setMid() {
        int size = items.size();
        for(int i =0 ; i<size; i++){
            margin = items.get(i).rect.top - (cycleR - itemHeight / 2);
            if(Math.abs(margin) <= itemHeight /2 && Math.abs(margin) > 0){
                t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                       isRun = true;
                       for(float i = Math.abs(margin); i > Math.abs(margin) / 10; i -= Math.abs(margin) / 10){
                           try{
                                if(isRun){
                                    sort(-margin / 10);
                                    Thread.sleep(10);
                                    myHandler.sendEmptyMessage(1);
                                }else{
                                    break;
                                }
                           }catch (InterruptedException e){

                           }
                       }
                       isRun = false;
                    }
                });
                t.start();
                break;
            }
        }
    }

    private boolean isInTouchArea(MotionEvent event) {
        if(event.getX() >= cycleR * 3 / 4 && event.getX() <= cycleR * 2 && event.getY() > 0 && event.getY() < cycleR * 2){
            return true;
        }
        return false;
    }

    private SelectItem getItem(MotionEvent event) {
        int size = items.size();
        for(int i =0; i< size; i++){
            if(items.get(i).isVisible(cycleR * 2)){
                if(items.get(i).isInRect(event.getX(), event.getY())){
                    return items.get(i);
                }
            }
        }
        return null;
    }

    public void onSelectListener(SelListener sl) {
          if(sl != null){
              this.sl = sl;
          }
    }
}
